Technical Note TN2026
Multilingual Text Engine Frequently Asked Questions

目次

このテクニカルノートは、MLTE(Multilingual Text Engine)について頻繁に質問される事項とその答えをまとめたものです。

[2001年7月11日]






入手方法と動作環境

Q: MLTE API はどこで入手できますか?また、アップルは TextEdit に代えて MLTE を利用するエディットテキストコントロールを作成するためのAPIに言及していました。CreateEditUnicodeTextControlという名前の API だそうですが、このAPIはどこで入手できますか?

A: MLTE API は Mac OS X 10.0 以降、Mac OS 8.6 以降に対応した CarbonLib の全バージョン、および Mac OS 9.0 以降で利用できます。

Unicode エディットテキストコントロールは Mac OS X 10.0 以降で利用できます。Unicode エディットテキストコントロールは CarbonLib では利用できません。

先頭に戻る

ビューレクタングルとデスティネーションレクタングルの管理

Q: MLTEオブジェクトでビューレクタングルとデスティネーションレクタングルを設定、変更する方法は?

A: オブジェクトの作成時に、TXNNewObject 関数によってビューレクタングルとデスティネーションレクタングルの両方が設定されます。値は入力パラメータに応じて次のように変わります。

a) iFrame が NULL の場合(ウィンドウの場合)
オブジェクトの作成時に kTXNAlwaysWrapAtViewEdgeMask フレームオプションを利用していない場合は、ビューレクタングルにはウィンドウの境界が、デスティネーションレクタングルにはデフォルト値が設定されます。CarbonLib と Mac OS 9 の場合は、現在選択されている用紙サイズ(「ページ設定」)がデフォルト値になります。Mac OS X の場合は、デフォルト値は(今のところ)定数です。

kTXNAlwaysWrapAtViewEdgeMask フレームオプションを利用している場合は、ビューレクタングルにはウィンドウの境界が、デスティネーションレクタングルにはウィンドウの境界からスクロールバーの幅を除いた値が設定されます(スクロールバーが要求されていた場合)。

b) iFrame が有効なレクタングルへのポインタになっている場合(ペインの場合)
kTXNAlwaysWrapAtViewEdgeMask が有効であっても無効であっても、初期の動作は同じです。ビューレクタングル(オブジェクト作成時にスクロールバーが要求されていた場合はスクロールバーも含む)には入力レクタングルと同じ値が設定されます。デスティネーショレクタングルには入力レクタングルからスクロールバーの幅を除いた値が設定されます(スクロールバーが要求されていた場合)。

では、MLTE クライアントでビューレクタングルとデスティネーションレクタングルの調節ができるようにする API について説明しましょう。

ビューレクタングルだけを設定し、デスティネーションレクタングルは変更せずそのままにしておくというのが関数 TXNSetFrameBounds の標準的な動作です。しかし、kTXNAlwaysWrapAtViewEdgeMask を利用している場合はビューレクタングルとデスティネーションレクタングルが同じ値になるように維持されるため、結果的に両方のレクタングルの値が設定されることになります。

関数 TXNResizeFrame はビューレクタングルとデスティネーションレクタングルの両方を設定します。ビューレクタングルの幅と高さには、それぞれ入力の幅と高さが設定されます。垂直スクロールバーが存在する場合は、デスティネーションレクタングル幅には入力の幅からスクロールバーの幅を除いた値が設定されます。MTLE モデルではデスティネーションレクタングルの高さが無限大であると想定されているため、高さは変更されません。

関数 TXNGETVIEWRECT が現在のビューレクタングルを取得します。スクロールバー領域が存在する場合、それはレクタングルの一部と見なされます。

今のところ、MLTE には現在のデスティネーションレクタングルを設定したり取得したりする関数はありません。しかし、ビューレクタングルやデスティネーションレクタングルを別の値に設定する必要がある場合は、関数 TXNResizeFrame に続いて TXNSetFrameBounds を呼び出すことによって、これを行うことができます。関数 TXNResizeFrame はデスティネーションレクタングルとビューレクタングルの両方を設定し、関数 TXNSetFrameBounds はビューレクタングルの境界を設定します。

では、kTXNAlwaysWrapAtViewEdgeMask オプションを詳しく見ていきましょう。このオプションが指定されていると、ビューレクタングルとデスティネーションレクタングルが強制的に同調されます(スクロールバーの分、わずかに異なる値を取ります)。たとえばウィンドウのサイズが変更されると、テキストのレイアウトが計算し直されます。これは、たとえばMLTEオブジェクトがウィンドウの幅一杯に表示されているときにテキストが必ずウィンドウの端で折り返されるようにしたい場合に便利です。

先頭に戻る

MLTEでQuartzを利用するには

Q: システムの他の部分と同じように、Mac OS X でアンチエイリアス化されたテキストを MLTE にレンダリングさせたいと思います。MLTEはこの機能をサポートしていますか?

A: MLTE は Mac OS X 10.0 以降の環境で Quartz のアンチエイリアス化されたテキストをサポートします。これを行うには、クライアント側で CG コンテキストを作成し、関数 TXNSetTXNObjectControls を利用してMLTEに渡します。以下に Quartz によるレンダリングを有効にするサンプルコードを示します。

TXNControlTag  controlTags[] = { kATSUCGContextTag };
 TXNControlData  controlData[1];
 CGContextRef  cgContext;

 if ( CreateCGContextForPort( aGrafPort, &cgContext ) == noErr )
 {

  controlData[0].uValue = (UInt32) cgContext;
  status = TXNSetTXNObjectControls(
    theMLTEObject,
    false,
    sizeof( controlTags ) / sizeof( TXNControlTag ),
    controlTags,
    controlData );
 }

先頭に戻る

カーソルの表示について

Q: MLTE オブジェクトにフォーカスが当たっていない場合(TXNFocus(txnObject, false))、カーソルが点線のようになります。別のテキストエンジンを使ったときは、MLTE オブジェクトにフォーカスが当たっていないときにはカーソルが表示されませんでした。MLTE でも同じようにする方法は?

A: Mac OS X 10.0 以降、および CarbonLib 1.2 以降の MLTE には、オブジェクトにフォーカスが当たっていない場合のカーソルやテキストの外観を柔軟に変更できるフレームオプションがいくつか用意されました。このフレームオプションは、関数 TXNNewObject を使ってオブジェクトを作成すると設定されます。

フレームオプション
kTXNDontDrawCaretWhenInactiveMask を指定することにより、テキストオブジェクトにフォーカスが当たっていないときにカーソルが描画されないようになります。一方、テキストオブジェクトにフォーカスが当たっていないときにセレクト範囲(もしあれば)が描画されないようにするには、フレームオプション kTXNDontDrawSelectionWhenInactiveMask を指定します。

MLTE オブジェクトの作成時にこれらのオプションを設定すると、オブジェクトにフォーカスが当たっていないときにカーソルが表示されないようになります。

また、制御タグ kTXNDrawCaretWhenInactiveTag と kTXNDrawSelectionWhenInactiveTag、およびこれに対応する値 kTXNDontDrawCaretWhenInactive、kTXNDrawCaretWhenInactive、kTXNDontDrawSelectionWhenInactive、kTXNDrawSelectionWhenInactive を関数 TXNSetTXNObjectControls に渡して利用できるようになりました。これらの制御タグと対応する値は、オブジェクトの作成後にアクティブでないキャレットとセレクト範囲(もしあれば)の見え方を調整するために利用できます。

先頭に戻る

テキストスタイル属性の設定

Q: 現在のセレクト範囲の色、大きさ、スタイルを設定するには?

A: 関数 TXNSetTypeAttributes を使えば、1 回の呼び出しで 1 つ以上のテキスト属性を設定できます。以下に現在のセレクト範囲を太字で赤色の36 ポイントに設定するコードの例を示します。

 // タイプ属性データ構造体を作成
 RGBColor  fontColor = { 0xFFFF, 0, 0 };
 UInt32   fontSize = 36 << 16; // needs to be in Fixed format
 TXNTypeAttributes attributes[] = {
         { kTXNQDFontStyleAttribute, kTXNQDFontStyleAttributeSize, bold },
         { kTXNQDFontColorAttribute, kTXNQDFontColorAttributeSize, &fontColor },
        { kTXNQDFontSizeAttribute, kTXNQDFontSizeAttributeSize, fontSize }
 };

 // TXNSetTypeAttributesの呼び出し
 status = TXNSetTypeAttributes( myMLTEObject, 3, attributes,
      kTXNUseCurrentSelection,
      kTXNUseCurrentSelection );

ここでは関数 TXNSetTypeAttributes の呼び出しに対してメタオフセット kTXNUseCurrentSelection を指定しています。しかし、有効なオフセットである限り、任意の範囲のオフセットを指定してこの関数を呼び出せます。また、この関数の呼び出し時に属性を1つずつ指定することにより、フォントスタイル、色、フォントサイズを個別に設定できます。

先頭に戻る

フォントの設定

Q: 現在のセレクト範囲のフォントを設定するには?

A: まず、使いたいフォントの ATSUFontID を取得する必要があります。次に関数 TXNSetTypeAttributes を利用して、取得したIDをMLTEに渡します。たとえば、MLTE オブジェクト内の現在のセレクト範囲を "Apple Chancery" で表示するには、次のようにします。

//ATSUIフォントIDの取得
 Str255 fontName  ="¥pApple Chancery";
 ATSUFontID   fontID;

 status = ATSUFindFontFromName(
   (Ptr) fontName+1, 
   (long) fontName[0], 
   kFontFullName,
   kFontNoPlatform,
   kFontNoScript,
   kFontNoLanguage,   
   &fontID );

 //関数TXNSetTypeAttributesを利用してATSUIフォントIDをMLTEへ渡す
 TXNTypeAttributes     attributes[] = 
      {kATSUFontTag, sizeof(ATSUFontID), {0}};

 attributes.data.dataValue = fontID;
 status = TXNSetTypeAttributes( myMLTEObject, 1, attributes,
    kTXNUseCurrentSelection,  kTXNUseCurrentSelection );

Apple Developer ウェブサイト <http://developer.apple.com/> に、他にも ATSUI のAPI に関する資料があります。

先頭に戻る

フォントの取得

Q: MLTE で、任意のスタイルランで使われているフォントを知るには?

A: スタイルランで使われている ATSUI フォント ID を知るには、関数 TXNGetContinuousTypeAttributes を利用します。以下に例を示します。

ATSUFontID   fontID;
 TXNContinuousFlags     continuousFlags;
 TXNTypeAttributes     attributes[] = 
      {kATSUFontTag, sizeof(ATSUFontID), {0}};

 TXNGetContinuousTypeAttributes( myMLTEObject, 
  &continuousFlags, 1,  attributes);

 fontID = attributes[0].data.dataValue;

先頭に戻る

スクロールバーのレンダリング

Q: 現在、MLTE オブジェクトを作成しています(オブジェクトの初期のレクタングルが指定された状態です)。しかし、TXNResizeFrame を呼び出したときにスクロールバーが正しくレンダリングされません。具体的にいえば、スクロールバーの内側には境界線がありますが、外側にはありません。また、スクロールバーの一番上に変更前のサイズのときの名残りのようなものがあります。何かアドバイスはありませんか?

A: ご質問の問題を解決するには、関数 InvalWindowRect を呼び出し、MLTE オブジェクトが利用していた古いビューレクタングルを無効にする必要があります。TXNGetViewRect を使ってオブジェクトのビューレクタングルを取得するとき、この関数から返されるレクタングルにはスクロールバーの外側の境界線は一切含まれません。したがって、この場合には、まず InsetRect( &myMLTEObjectViewRect, -1, -1) を呼び出して周囲全体を1ピクセル分大きくし、それからその拡大したレクタングルに対し InvalWindowRect を呼び出すようにします。

ペインオブジェクトで TXNSetFrameBounds を利用する場合も同じ方法を用います。

先頭に戻る

Carbon アプリケーション

Q: MLTE を使うアプリケーションを Carbon に対応させようとしています。API の呼び出しに違いはありますか?

A: Carbon アプリケーションでは TXNTSMCheck は呼び出せません。 これは、Carbon の場合、TSM(Text Services Manager)が自動的に初期化されるためです。また、TXNIdle や TXNKeydown を呼び出す必要はありません。Carbon の場合、MLTE はカーソルを点滅させるタイマーをインストールするため、アプリケーションで関数 TXNIdle を呼び出す必要はありません。また、TSM はキーダウンを直接 MLTE の UnicodeForKeyEvent ハンドラに送るため、TXNObject にフォーカスがあるとアプリケーションはキーダウンを受け取れません。

Mac OS 10.0 と CarbonLib 1.3 では、MLTE の Carbon イベントハンドラをサポートするため、データ構造体 TXNCarbonEventInfo が用意されています。この機能の導入により、MLTE の Carbon アプリケーションはテキスト入力イベントの Carbon イベントモデルを十分に活用することができるようになりました。

先頭に戻る

Carbonイベント

Q: MLTE で Carbon イベントのサポートを有効にするには?

A: デフォルトでは、MLTE はテキストの入力に Apple Event Manager を利用します。しかし、データ構造体 TXNCarbonEventInfo が最近追加されたため、MLTE クライアントで、テキスト入力処理に MLTE が Carbon イベントを利用するように指定できます。MLTE オブジェクト用に MLTE が Carbon イベントをサポートするように設定するには、次のようにします。

  1. イベントターゲットの辞書を作成します。
  2. 独自のアクションキーマッピング・コールバック関数を用意します(省略可能)。
  3. MLTE に処理させたい各イベントに関する情報を渡し、構造体 TXNCarbonEventInfo をインスタンス化します。
  4. 関数 TXNSetTXNObjectControls を呼び出します。

以下にテキスト入力イベント向けに MLTECarbon イベントハンドラを有効にするサンプルコードを示します。

// 変数の宣言
 TXNControlTag  controlTags[] = { kTXNUseCarbonEvents };
 TXNControlData  controlData[1];
 TXNCarbonEventInfo carbonEventInfo;
 CFStringRef   keys[] = { kTXNTextInputHandlerKey };
 EventTargetRef  values[] =
      { GetWindowEventTarget( myWindowRef ) };


 // Carbon のテキストイベントを処理するための
 // データ構造体 TXNCarbonEventInfo を初期化
 carbonEventInfo.useCarbonEvents = true;
 carbonEventInfo.filler = 0;
 carbonEventInfo.flags = kTXNNoAppleEventHandlersMask;
 carbonEventInfo.fDictionary =

 CFDictionaryCreate( kCFAllocatorDefault, 
    (const void **) &keys, 
    (const void **) &values, 
    1, 
   &kCFCopyStringDictionaryKeyCallBacks, 
   NULL );

 controlData[0].uValue = (UInt32) &carbonEventInfo;

 // Carbon ハンドラをインストールするよう MLTE へ通知
 status = TXNSetTXNObjectControls(
   theMLTEObject,
   false,
   sizeof( controlTags ) / sizeof( TXNControlTag ),
   controlTags,
   controlData );

 // 辞書のリリース
 CFRelease( carbonEventInfo.fDictionary );

パフォーマンスに関するヒント

Q: TXNObject の内容をクリアする最良の方法は?

A: MLTE オブジェクトの内容をクリアするには、NULL ポインタを渡して関数 TXNSetData を呼び出します。

Q: kTXNAlwaysWrapAtViewEdgeBit を無効にしています。TXNResizeFrame は TXNSetFrameBounds と同程度の処理速度が期待できますか?

A: kTXNAlwaysWrapAtViewEdgeBit が無効の場合は、TXNResizeFrame は TXNSetFrameBounds ほどの処理速度にはなりません。TXNResizeFrame には TXNSetFrameBounds が行わないテキストの再レイアウトが伴うため、処理速度に違いが出ます。TXNSetFrameBounds はビューレクタングルとデスティネーションレクタングルの両方を設定するため、テキストの再レイアウトが生じます。それに対し TXNSetFrameBounds はビューレクタングルの境界だけを設定するため、テキストの再レイアウトは不要です。

kTXNAlwaysWrapAtViewEdgeBit は TXNResizeFrame のためには何もしません。TXNResizeFrame を呼び出すと、(垂直スクロールバーがもしあれば、その分を除いた)ビューレクタングルの端でテキストが折り返されるように、ビューレクタングルとデスティネーションレクタングルがリセットされます。

先頭に戻る

-->